package com.fau.wmbj.server.utils;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

/**
 * 查询筛选
 *
 * @author jiawei
 */
public class Filter implements Serializable {

    private static final long serialVersionUID = -8712382358441065075L;
    /**
     * 默认是否忽略大小写
     */
    private static final boolean DEFAULT_IGNORE_CASE = false;
    /**
     * 属性
     */
    private String property;
    /**
     * 运算符
     */
    private Operator operator;
    /**
     * 值
     */
    private Object value;

    /**
     * 是否忽略大小写
     */
    private Boolean ignoreCase = DEFAULT_IGNORE_CASE;

    /**
     * 子条件
     */
    private List<Filter> filters;

    /**
     * 构造方法
     */
    public Filter() {
    }

    /**
     * 构造方法
     *
     * @param operator 运算符
     * @param filters  值
     */
    public Filter(Operator operator, List<Filter> filters) {
        this.operator = operator;
        this.filters = filters;
    }

    /**
     * 构造方法
     *
     * @param property 属性
     * @param operator 运算符
     * @param value    值
     */
    public Filter(String property, Operator operator, Object value) {
        this.property = property;
        this.operator = operator;
        this.value = value;
    }

    /**
     * 构造方法
     *
     * @param property   属性
     * @param operator   运算符
     * @param value      值
     * @param ignoreCase 忽略大小写
     */
    public Filter(String property, Operator operator, Object value, boolean ignoreCase) {
        this.property = property;
        this.operator = operator;
        this.value = value;
        this.ignoreCase = ignoreCase;
    }

    /**
     * 或者
     *
     * @param filters 值
     * @return 或者筛选
     */
    public static Filter or(List<Filter> filters) {
        return new Filter(Operator.or, filters);
    }

    /**
     * 或者
     *
     * @param filters 值
     * @return 或者筛选
     */
    public static Filter or(Filter... filters) {
        return new Filter(Operator.or, ArrayUtils.isNotEmpty(filters) ? Arrays.asList(filters) : null);
    }

    /**
     * 一对多,多方为空
     *
     * @param property 属性
     * @return 或者筛选
     */
    public static Filter subEmpty(String property) {
        return new Filter(property, Operator.subEmpty, null);
    }

    /**
     * 一对多,多方不为空
     *
     * @param property 属性
     * @return 或者筛选
     */
    public static Filter subNotEmpty(String property) {
        return new Filter(property, Operator.subEmpty, null);
    }


    /**
     * 返回等于筛选
     *
     * @param property 属性
     * @param value    值
     * @return 等于筛选
     */
    public static Filter eq(String property, Object value) {
        return new Filter(property, Operator.eq, value);
    }

    /**
     * 返回等于筛选
     *
     * @param property   属性
     * @param value      值
     * @param ignoreCase 忽略大小写
     * @return 等于筛选
     */
    public static Filter eq(String property, Object value, boolean ignoreCase) {
        return new Filter(property, Operator.eq, value, ignoreCase);
    }

    /**
     * 返回不等于筛选
     *
     * @param property 属性
     * @param value    值
     * @return 不等于筛选
     */
    public static Filter ne(String property, Object value) {
        return new Filter(property, Operator.ne, value);
    }

    /**
     * 返回不等于筛选
     *
     * @param property   属性
     * @param value      值
     * @param ignoreCase 忽略大小写
     * @return 不等于筛选
     */
    public static Filter ne(String property, Object value, boolean ignoreCase) {
        return new Filter(property, Operator.ne, value, ignoreCase);
    }

    /**
     * 返回大于筛选
     *
     * @param property 属性
     * @param value    值
     * @return 大于筛选
     */
    public static Filter gt(String property, Object value) {
        return new Filter(property, Operator.gt, value);
    }

    /**
     * 返回小于筛选
     *
     * @param property 属性
     * @param value    值
     * @return 小于筛选
     */
    public static Filter lt(String property, Object value) {
        return new Filter(property, Operator.lt, value);
    }

    /**
     * 返回大于等于筛选
     *
     * @param property 属性
     * @param value    值
     * @return 大于等于筛选
     */
    public static Filter ge(String property, Object value) {
        return new Filter(property, Operator.ge, value);
    }

    /**
     * lessThan
     *
     * @param property 属性
     * @param value    值
     * @return lessThan
     */
    public static Filter lessThan(String property, Object value) {
        return new Filter(property, Operator.lessThan, value);
    }

    /**
     * lessThanOrEqualTo
     *
     * @param property 属性
     * @param value    值
     * @return lessThan
     */
    public static Filter lessThanOrEqualTo(String property, Object value) {
        return new Filter(property, Operator.lessThanOrEqualTo, value);
    }

    /**
     * greaterThan
     *
     * @param property 属性
     * @param value    值
     * @return greaterThan
     */
    public static Filter greaterThan(String property, Object value) {
        return new Filter(property, Operator.greaterThan, value);
    }

    /**
     * greaterThanOrEqualTo
     *
     * @param property 属性
     * @param value    值
     * @return lessThan
     */
    public static Filter greaterThanOrEqualTo(String property, Object value) {
        return new Filter(property, Operator.greaterThanOrEqualTo, value);
    }

    /**
     * 返回小于等于筛选
     *
     * @param property 属性
     * @param value    值
     * @return 小于等于筛选
     */
    public static Filter le(String property, Object value) {
        return new Filter(property, Operator.le, value);
    }

    /**
     * 返回相似筛选
     *
     * @param property 属性
     * @param value    值
     * @return 相似筛选
     */
    public static Filter like(String property, Object value) {
        return new Filter(property, Operator.like, value);
    }

    /**
     * 返回Long类型json数据的in条件查询筛选
     *
     * @param property 属性
     * @param value    值
     * @return 相似筛选
     */
    public static Filter arrayLongsIn(String property, Object value) {
        return new Filter(property, Operator.arrayLongsIn, value);
    }

    /**
     * 返回包含筛选
     *
     * @param property 属性
     * @param value    值
     * @return 包含筛选
     */
    public static Filter in(String property, Object value) {
        return new Filter(property, Operator.in, value);
    }

    /**
     * 返回为Null筛选
     *
     * @param property 属性
     * @return 为Null筛选
     */
    public static Filter isNull(String property) {
        return new Filter(property, Operator.isNull, null);
    }

    /**
     * 返回不为Null筛选
     *
     * @param property 属性
     * @return 不为Null筛选
     */
    public static Filter isNotNull(String property) {
        return new Filter(property, Operator.isNotNull, null);
    }

    /**
     * 返回忽略大小写筛选
     *
     * @return 忽略大小写筛选
     */
    public Filter ignoreCase() {
        this.ignoreCase = true;
        return this;
    }

    /**
     * 获取属性
     *
     * @return 属性
     */
    public String getProperty() {
        return property;
    }

    /**
     * 设置属性
     *
     * @param property 属性
     */
    public void setProperty(String property) {
        this.property = property;
    }

    /**
     * 获取运算符
     *
     * @return 运算符
     */
    public Operator getOperator() {
        return operator;
    }

    /**
     * 设置运算符
     *
     * @param operator 运算符
     */
    public void setOperator(Operator operator) {
        this.operator = operator;
    }

    /**
     * 获取值
     *
     * @return 值
     */
    public Object getValue() {
        return value;
    }

    /**
     * 设置值
     *
     * @param value 值
     */
    public void setValue(Object value) {
        this.value = value;
    }

    /**
     * 获取是否忽略大小写
     *
     * @return 是否忽略大小写
     */
    public Boolean getIgnoreCase() {
        return ignoreCase;
    }

    /**
     * 设置是否忽略大小写
     *
     * @param ignoreCase 是否忽略大小写
     */
    public void setIgnoreCase(Boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
    }

    public List<Filter> getFilters() {
        return filters;
    }

    public void setFilters(List<Filter> filters) {
        this.filters = filters;
    }

    /**
     * 重写equals方法
     *
     * @param obj 对象
     * @return 是否相等
     */
    @Override
    public boolean equals(Object obj) {
        return EqualsBuilder.reflectionEquals(this, obj);
    }

    /**
     * 重写hashCode方法
     *
     * @return HashCode
     */
    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }

    /**
     * 运算符
     */
    public enum Operator {
        /**
         * 2 in [1,2,3]
         */
        arrayLongsIn,
        /**
         * 一对多,多方为空
         */
        subEmpty,
        /**
         * 一对多,多方不为空
         */
        subNotEmpty,
        /**
         * 或者
         */
        or,

        /**
         * 等于
         */
        eq,

        /**
         * 不等于
         */
        ne,

        /**
         * 大于
         */
        gt,

        /**
         * 小于
         */
        lt,

        /**
         * 大于等于
         */
        ge,

        /**
         * 小于等于
         */
        le,

        /**
         * 相似
         */
        like,

        /**
         * 包含
         */
        in,

        /**
         * 为Null
         */
        isNull,

        /**
         * 不为Null
         */
        isNotNull,
        /**
         * lessThan
         */
        lessThan,
        /**
         * lessThan
         */
        greaterThan,
        /**
         * lessThanOrEqualTo
         */
        lessThanOrEqualTo,
        /**
         * greaterThanOrEqualTo
         */
        greaterThanOrEqualTo
    }
}